Skip to content

CONSOLE-5296: Add non-scalable image warning when scaling workloads#16436

Open
swshende-cmd wants to merge 6 commits into
openshift:mainfrom
swshende-cmd:RFE-3935
Open

CONSOLE-5296: Add non-scalable image warning when scaling workloads#16436
swshende-cmd wants to merge 6 commits into
openshift:mainfrom
swshende-cmd:RFE-3935

Conversation

@swshende-cmd
Copy link
Copy Markdown

@swshende-cmd swshende-cmd commented May 12, 2026

Summary

  • Adds a warning when users attempt to scale a workload beyond one replica if the container image has the io.openshift.non-scalable=true label in its metadata
  • Warning appears as an inline alert in the "Edit Pod count" modal and as a tooltip on the PodRing scale-up button
  • Implements a useNonScalableImageCheck hook that resolves ImageStreamTag references from Deployment trigger annotations or DeploymentConfig ImageChange triggers, watches the IST via useK8sWatchResource, and checks image.dockerImageMetadata.Config.Labels for the non-scalable label

JIRA

CONSOLE-5296 (created from RFE-3935)

Changes

File Change
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts New — Hook using useK8sWatchResource to check for io.openshift.non-scalable label on an ImageStreamTag
frontend/public/components/modals/configure-count-modal.tsx Inline warning alert when scaling non-scalable images above 1 replica; hook gated by isReplicaPath
frontend/packages/console-shared/src/components/pod/PodRing.tsx Tooltip on scale-up button for non-scalable images; deduplicated Button JSX
frontend/public/locales/en/public.json i18n strings for modal warning
frontend/packages/console-shared/locales/en/console-shared.json i18n strings for PodRing tooltip
frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts New — 9 unit tests for the hook
frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx New — 6 unit tests for the modal warning (includes userEvent increment test)

Screenshots / Recordings

To be added by author

Test plan

  • Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1 replica
  • Tooltip appears on PodRing scale-up arrow for non-scalable images
  • No warning for regular (scalable) images
  • No warning for Deployments without ImageStream triggers
  • No warning for Job parallelism path
  • Unit tests pass: yarn test packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts (9 tests)
  • Unit tests pass: yarn test public/components/modals/__tests__/configure-count-modal.spec.tsx (6 tests)

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added detection and user-facing warnings for images marked non-scalable; warnings appear when increasing pod count and when editing replica count above one.
  • Localization

    • Added localized warning strings explaining non-scalable image constraints.
  • Tests

    • Added unit tests covering non-scalable image detection and warning display in relevant UIs.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 12, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 12, 2026

@swshende-cmd: This pull request references RFE-3935 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the feature request to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Adds a warning when users attempt to scale a workload beyond one replica if the container image has the io.openshift.non-scalable=true label in its metadata
  • Warning appears as an inline alert in the "Edit Pod count" modal and as a tooltip on the PodRing scale-up button
  • Implements a useNonScalableImageCheck hook that resolves ImageStreamTag references from Deployment trigger annotations or DeploymentConfig ImageChange triggers, fetches the IST, and checks image.dockerImageMetadata.Config.Labels for the non-scalable label

JIRA

RFE-3935

Changes

File Change
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts New — Hook to check for io.openshift.non-scalable label on an ImageStreamTag
frontend/public/components/modals/configure-count-modal.tsx Inline warning alert when scaling non-scalable images above 1 replica
frontend/packages/console-shared/src/components/pod/PodRing.tsx Tooltip on scale-up button for non-scalable images
frontend/public/locales/en/public.json i18n strings for modal warning
frontend/packages/console-shared/locales/en/console-shared.json i18n strings for PodRing tooltip
frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts New — 7 unit tests for the hook
frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx New — 4 unit tests for the modal warning

Screenshots / Recordings

To be added by author

Test plan

  • Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1 replica
  • Tooltip appears on PodRing scale-up arrow for non-scalable images
  • No warning for regular (scalable) images
  • No warning for Deployments without ImageStream triggers
  • No warning for Job parallelism path
  • Unit tests pass: yarn test packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts (7 tests)
  • Unit tests pass: yarn test public/components/modals/__tests__/configure-count-modal.spec.tsx (4 tests)

Made with Cursor

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot requested review from jhadvig and spadgett May 12, 2026 16:08
@openshift-ci openshift-ci Bot added component/core Related to console core functionality component/shared Related to console-shared kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels May 12, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 12, 2026

Hi @swshende-cmd. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

Adds a hook to detect ImageStreamTags labeled io.openshift.non-scalable, surfaces warnings in PodRing and ConfigureCountModal when scaling beyond one replica, includes tests, and updates English locale strings.

Changes

Non-scalable image detection and UI warnings

Layer / File(s) Summary
IST reference extraction & helpers
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts
New helpers to derive an ImageStreamTag reference from a resource: parses DeploymentConfig.spec.triggers ImageChange triggers and image.openshift.io/triggers annotation JSON for Deployments.
Hook implementation
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts
Adds exported useNonScalableImageCheck(resource) hook: memoizes IST ref, fetches the IST via k8sGet(ImageStreamTagModel, name, namespace), reads image.dockerImageMetadata.Config.Labels, sets { isNonScalable, loading }, handles string/boolean "true", catches errors, and guards updates with a cancellation flag.
PodRing integration
frontend/packages/console-shared/src/components/pod/PodRing.tsx
Calls useNonScalableImageCheck(obj); when user attempts to increase pod count (clickCount >= 1) and isNonScalable is true, wraps the increase button in a PatternFly Tooltip showing the non-scalable warning.
ConfigureCountModal integration
frontend/public/components/modals/configure-count-modal.tsx, frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx
Uses useNonScalableImageCheck inside the modal; when editing /spec/replicas and entered value > 1 with isNonScalable, renders an inline Alert with translated copy. Tests mock the hook and validate warning visibility across replica and path scenarios.
Unit tests for the hook
frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts
New Jest suite covering: DC triggers and annotation parsing, IST label values as string or boolean, no-image-trigger paths (no k8sGet), error handling, and loading state transitions.
Locale additions
frontend/packages/console-shared/locales/en/console-shared.json, frontend/public/locales/en/public.json
Adds English strings for the non-scalable title and explanatory message; adjusts JSON tail in public.json to update final entries.
sequenceDiagram
    participant UI as UI (PodRing / Modal)
    participant Hook as useNonScalableImageCheck
    participant API as kube API / k8sGet
    participant IST as ImageStreamTag

    UI->>Hook: provide resource
    Hook->>Hook: parse triggers/annotation -> IST ref?
    alt IST ref found
        Hook->>API: k8sGet(ImageStreamTag)
        API->>IST: fetch IST
        IST-->>API: IST data (includes dockerImageMetadata.Config.Labels)
        API-->>Hook: IST payload
        Hook->>Hook: inspect label io.openshift.non-scalable (true/'true')
        Hook-->>UI: {isNonScalable: true, loading:false}
        UI->>UI: show tooltip/alert when user increases replicas >1
    else no IST ref or error
        Hook-->>UI: {isNonScalable:false, loading:false}
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 12
✅ Passed checks (12 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed Custom check targets Ginkgo tests (.go files with Describe/It). PR contains only Jest tests (.spec.ts/.spec.tsx). Ginkgo is a Go test framework; this is a frontend feature PR. Check is not applicable.
Test Structure And Quality ✅ Passed Custom check requires reviewing Ginkgo test code, but this PR contains only Jest tests. No Ginkgo tests present, so check is not applicable.
Microshift Test Compatibility ✅ Passed PR contains no Ginkgo e2e tests. All changes are frontend TypeScript/React code with Jest unit tests. The MicroShift compatibility check for Ginkgo e2e tests does not apply.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests present in this PR. All test files are Jest unit tests (TypeScript), not Go-based e2e tests. Check not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed PR contains only frontend/UI changes (React hooks, components, tests, i18n). No deployment manifests, operator code, controllers, or scheduling constraints are introduced. Only user warnings.
Ote Binary Stdout Contract ✅ Passed This PR only modifies frontend TypeScript/JSON files. It contains no Go code, test binaries, or process-level code subject to OTE Binary Stdout Contract requirements.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR contains no Ginkgo e2e tests. All tests are Jest unit tests for frontend React components in TypeScript. The custom check for IPv6/disconnected compatibility targets Go-based Ginkgo e2e tests only.
Title check ✅ Passed The PR title clearly and specifically describes the main feature: adding a non-scalable image warning when users attempt to scale workloads beyond one replica.
Description check ✅ Passed The PR description is well-structured and covers all required sections: JIRA reference (CONSOLE-5296), clear solution summary, comprehensive file-level changes, test plan with specific test cases, and proper reviewer annotations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts`:
- Line 71: The effect is unstable because it depends on the istRef object
reference (const istRef = useMemo(() => getISTReference(resource), [resource]))
which changes when resource refreshes even if name/namespace are identical;
update the effect dependency to use stable primitives instead (e.g. istRef.name
and istRef.namespace or a derived string key) so the k8sGet call only runs when
the IST identity actually changes; locate getISTReference/istRef and the effect
that calls k8sGet and replace the istRef object dependency with those stable
properties or a memoized string.
- Around line 20-21: The current logic in useNonScalableImageCheck.ts only
examines the first annotation trigger and accepts any DeploymentConfig
ImageChange trigger without verifying its kind, which can mask a valid
ImageStreamTag (IST) trigger elsewhere; update the code that finds
imageChangeTrigger (the triggers.find call) to instead iterate all triggers and
select one whose type === 'ImageChange' and whose imageChangeParams.from.kind
=== 'ImageStreamTag' (or validate kind before using .name), and likewise update
the annotation-trigger handling to scan all annotation entries (not just the
first) to detect any IST annotations before resolving the IST; ensure you
reference and modify the imageChangeTrigger selection and the annotation parsing
logic so only true IST triggers are treated as valid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 606ab21e-dc84-48b0-8c21-1d33ecbb5d2b

📥 Commits

Reviewing files that changed from the base of the PR and between 9d4903e and d3be8ba.

📒 Files selected for processing (7)
  • frontend/packages/console-shared/locales/en/console-shared.json
  • frontend/packages/console-shared/src/components/pod/PodRing.tsx
  • frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts
  • frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts
  • frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx
  • frontend/public/components/modals/configure-count-modal.tsx
  • frontend/public/locales/en/public.json
📜 Review details
🔇 Additional comments (6)
frontend/public/locales/en/public.json (1)

1756-1757: LGTM!

frontend/packages/console-shared/locales/en/console-shared.json (1)

234-234: LGTM!

frontend/public/components/modals/configure-count-modal.tsx (1)

46-47: LGTM!

Also applies to: 101-112

frontend/packages/console-shared/src/components/pod/PodRing.tsx (1)

3-3: LGTM!

Also applies to: 10-10, 86-86, 131-157

frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx (1)

1-107: LGTM!

frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts (1)

1-147: LGTM!

Comment thread frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts Outdated
Comment thread frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts Outdated
@swshende-cmd
Copy link
Copy Markdown
Author

/verified by me

Please find below screen prints showing

  1. Tooltip appears on PodRing scale-up arrow for non-scalable images
  2. Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1
ToolTip_message_while_Hovering_onArrow Warning_appears_in_ Edit_Pod_count _modal

@openshift-ci-robot
Copy link
Copy Markdown
Contributor

@swshende-cmd: Jira verification commands are restricted to collaborators for this repo.

Details

In response to this:

/verified by me

Please find below screen prints showing

  1. Tooltip appears on PodRing scale-up arrow for non-scalable images
  2. Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1
ToolTip_message_while_Hovering_onArrow Warning_appears_in_ Edit_Pod_count _modal

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@dpateriya
Copy link
Copy Markdown

/verified by @swshende-cmd

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label May 12, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

@dpateriya: This PR has been marked as verified by @swshende-cmd.

Details

In response to this:

/verified by @swshende-cmd

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label May 12, 2026
@dpateriya
Copy link
Copy Markdown

/ok-to-test

@openshift-ci openshift-ci Bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels May 12, 2026
@swshende-cmd
Copy link
Copy Markdown
Author

/retest

@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 13, 2026

@swshende-cmd: This pull request references RFE-3935 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the feature request to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Adds a warning when users attempt to scale a workload beyond one replica if the container image has the io.openshift.non-scalable=true label in its metadata
  • Warning appears as an inline alert in the "Edit Pod count" modal and as a tooltip on the PodRing scale-up button
  • Implements a useNonScalableImageCheck hook that resolves ImageStreamTag references from Deployment trigger annotations or DeploymentConfig ImageChange triggers, fetches the IST, and checks image.dockerImageMetadata.Config.Labels for the non-scalable label

JIRA

RFE-3935

Changes

File Change
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts New — Hook to check for io.openshift.non-scalable label on an ImageStreamTag
frontend/public/components/modals/configure-count-modal.tsx Inline warning alert when scaling non-scalable images above 1 replica
frontend/packages/console-shared/src/components/pod/PodRing.tsx Tooltip on scale-up button for non-scalable images
frontend/public/locales/en/public.json i18n strings for modal warning
frontend/packages/console-shared/locales/en/console-shared.json i18n strings for PodRing tooltip
frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts New — 7 unit tests for the hook
frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx New — 4 unit tests for the modal warning

Screenshots / Recordings

To be added by author

Test plan

  • Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1 replica
  • Tooltip appears on PodRing scale-up arrow for non-scalable images
  • No warning for regular (scalable) images
  • No warning for Deployments without ImageStream triggers
  • No warning for Job parallelism path
  • Unit tests pass: yarn test packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts (7 tests)
  • Unit tests pass: yarn test public/components/modals/__tests__/configure-count-modal.spec.tsx (4 tests)

Made with Cursor

Summary by CodeRabbit

  • New Features

  • Added detection and user-facing warnings for images marked non-scalable; warnings appear when increasing pod count and when editing replica count above one.

  • Localization

  • Added localized warning strings explaining non-scalable image constraints.

  • Tests

  • Added unit tests covering non-scalable image detection and warning display in relevant UIs.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@swshende-cmd
Copy link
Copy Markdown
Author

/retest

@dpateriya
Copy link
Copy Markdown

/verified by @swshende-cmd

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label May 14, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

@dpateriya: This PR has been marked as verified by @swshende-cmd.

Details

In response to this:

/verified by @swshende-cmd

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link
Copy Markdown
Member

@jhadvig jhadvig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! The feature design is sound — the IST resolution logic for both DeploymentConfig triggers and Deployment annotation triggers is well done, and the error handling is sensible. A few structural issues to address before this can merge, mostly around aligning with project conventions.

import * as _ from 'lodash';
import { ImageStreamTagModel } from '@console/internal/models';
import type { K8sResourceKind } from '@console/internal/module/k8s';
import { k8sGet } from '@console/internal/module/k8s';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use useK8sWatchResource instead of imperative k8sGet

Every other data-fetching hook in console-shared/src/hooks/ uses the declarative useK8sWatchResource — including useRelatedHPA, the nearest peer hook also consumed by PodRing. Using k8sGet inside a useEffect with manual cancellation means:

  • No live updates if the IST label changes while the page is open
  • No shared cache — each component instance fires its own fetch
  • Manual cancelled flag boilerplate that the framework handles automatically

Suggested approach:

const [ist, loaded, error] = useK8sWatchResource<K8sResourceKind>(
  istName && istNamespace
    ? { kind: ImageStreamTagModel.kind, name: istName, namespace: istNamespace, isList: false }
    : null,
);
const isNonScalable = loaded && !error
  ? ist?.image?.dockerImageMetadata?.Config?.Labels?.['io.openshift.non-scalable'] === 'true'
  : false;
return { isNonScalable, loading: !loaded };

This eliminates the useState, useEffect, and cancellation logic entirely.

const istName = istRef?.name;
const istNamespace = istRef?.namespace;

useEffect(() => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useMemo depends on unstable resource object reference

resource is a K8s watch object whose reference changes on every watch cycle. This useMemo recomputes on every render, making it effectively a no-op. The downstream istName/istNamespace primitives save the useEffect from re-firing, but getISTReference() (which parses triggers and JSON-parses annotations) runs redundantly on every render.

If you switch to useK8sWatchResource (comment above), this becomes moot. If keeping the current approach, depend on stable primitives:

const triggerAnnotation = resource?.metadata?.annotations?.[IMAGE_TRIGGER_ANNOTATION];
const resourceKind = resource?.kind;
const resourceNamespace = resource?.metadata?.namespace;
const istRef = useMemo(
  () => getISTReference(resource),
  [resourceKind, resourceNamespace, triggerAnnotation],
);

onClick={() => handleClick(1)}
isBlock
/>
{isNonScalable && clickCount >= 1 ? (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deduplicate the Button JSX

The entire <Button> (8 identical prop lines) is duplicated — once with a <Tooltip> wrapper, once without. Extract the button and conditionally wrap:

const scaleUpButton = (
  <Button
    icon={<AngleUpIcon style={{ fontSize: '20' }} />}
    type="button"
    variant="plain"
    aria-label={t('console-shared~Increase the Pod count')}
    title={t('console-shared~Increase the Pod count')}
    onClick={() => handleClick(1)}
    isBlock
  />
);

// Then in the JSX:
{isNonScalable && clickCount >= 1 ? (
  <Tooltip content={t('console-shared~This image is not intended to run with more than one replica. Scaling up may cause unexpected behavior.')}>
    {scaleUpButton}
  </Tooltip>
) : scaleUpButton}

} = obj;
const [hpa] = useRelatedHPA(apiVersion, kind, name, namespace);
const hpaControlledScaling = !!hpa;
const { isNonScalable } = useNonScalableImageCheck(obj);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loading state is ignored — user can scale before the check completes

The hook returns { isNonScalable, loading } but both consumers (PodRing and ConfigureCountModal) destructure only isNonScalable. During the initial fetch, isNonScalable defaults to false, so the warning won't show until the IST fetch resolves. If the check matters enough to exist, consider disabling the scale-up button or showing a spinner while loading is true, to avoid a brief window where the user can scale without seeing the warning.

mockUseNonScalableImageCheck.mockReturnValue({ isNonScalable: false, loading: false });
});

it('should show warning when image is non-scalable and value > 1', () => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test for the primary user flow: spinning from 1 to 2

All four tests check initial render states, but the most important scenario is untested: a user opens the modal at 1 replica and uses the spinner to increase to 2. That's when the warning should dynamically appear. Consider adding a test using userEvent to click the increment button and assert the warning becomes visible.

const { t } = useTranslation();
const [handlePromise, inProgress, errorMessage] = usePromiseHandler();
const isReplicaPath = path === '/spec/replicas';
const { isNonScalable } = useNonScalableImageCheck(resource);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hook runs unconditionally even for non-replica paths (Jobs, etc.)

useNonScalableImageCheck will resolve IST triggers and fetch the ImageStreamTag even when path is /spec/parallelism (Jobs) where the warning is never shown. Consider gating the hook to avoid unnecessary API calls:

const { isNonScalable } = useNonScalableImageCheck(isReplicaPath ? resource : null);

The hook already handles null/missing triggers gracefully, so passing null when the check isn't needed would skip the fetch entirely. (Same applies to PodRing — the hook runs for every workload on the topology view, including bare Deployments without IST triggers.)

@@ -0,0 +1,114 @@
import { useState, useEffect, useMemo } from 'react';
import * as _ from 'lodash';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Full lodash import for a single _.get call. Only _.get(ist, 'image.dockerImageMetadata.Config.Labels', {}) is used. Consider optional chaining instead, which eliminates the lodash dependency entirely:

const labels = ist?.image?.dockerImageMetadata?.Config?.Labels ?? {};

(If you adopt useK8sWatchResource per the other comment, this becomes even simpler since there's no .then() callback at all.)

const mockUseNonScalableImageCheck = useNonScalableImageCheck as jest.Mock;

const baseProps = {
defaultValue: 0,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: defaultValue: 0 is misleading here. The first test overrides replicas: 2, so value initializes to 2 (from _.get(resource, getPath)). The defaultValue: 0 is never reached. Meanwhile baseProps has replicas: 1, making defaultValue: 0 dead code there too. Setting defaultValue: 1 would better reflect the actual test scenarios and avoid confusion for future readers.

onClick={() => handleClick(1)}
isBlock
/>
{isNonScalable && clickCount >= 1 ? (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Tooltip shows before the user has done anything. clickCount is initialized to obj.spec.replicas. When a workload is already at 1 replica, the tooltip appears on the up-arrow immediately — before the user has interacted. This might be intentional (preemptive warning), but worth confirming. If the intent is to warn only after attempting to scale up, the condition should be clickCount > 1 instead.

@jhadvig
Copy link
Copy Markdown
Member

jhadvig commented May 18, 2026

Also worth to mention that the correct workflow is to create CONSOLE project story from the RFE and reference that story.

@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label May 18, 2026
shendeswapnil6 and others added 5 commits May 18, 2026 20:43
Warn users when scaling a workload beyond one replica if its container
image has the io.openshift.non-scalable=true label. The warning appears
as an inline alert in the Edit Pod count modal and as a tooltip on the
PodRing scale-up button.

Adds a useNonScalableImageCheck hook that resolves ImageStreamTag
references from Deployment trigger annotations or DeploymentConfig
ImageChange triggers, fetches the IST, and inspects
image.dockerImageMetadata.Config.Labels for the non-scalable label.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Validate ImageStreamTag kind in DeploymentConfig triggers before resolving
- Scan all annotation triggers instead of only the first one
- Use stable primitives (name, namespace) as effect dependencies

Co-authored-by: Cursor <cursoragent@cursor.com>
Moves new i18n keys to the parser-determined position and removes
orphaned keys no longer referenced after the modal rewrite on main.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move Non-scalable image keys to parser-determined position (after
"Please enter a URL." at line 874) and restore all existing keys.
Remove trailing newline from console-shared.json to match parser output.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace imperative k8sGet with declarative useK8sWatchResource in
  useNonScalableImageCheck hook for live updates and shared cache
- Stabilize useMemo dependencies using primitive values instead of
  object references to avoid recomputing on every watch cycle
- Remove lodash dependency in favor of optional chaining
- Accept null resource param to skip the watch for non-replica paths
- Gate hook call with isReplicaPath in configure-count-modal
- Deduplicate scale-up Button JSX in PodRing with shared variable
- Add comment explaining preemptive tooltip at clickCount >= 1
- Rewrite hook tests to mock useK8sWatchResource instead of k8sGet
- Add userEvent increment test and fix defaultValue to 1 in modal tests

Co-authored-by: Cursor <cursoragent@cursor.com>
@swshende-cmd swshende-cmd changed the title RFE-3935: Add non-scalable image warning when scaling workloads CONSOLE-5296: Add non-scalable image warning when scaling workloads May 18, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 18, 2026

@swshende-cmd: This pull request references CONSOLE-5296 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Adds a warning when users attempt to scale a workload beyond one replica if the container image has the io.openshift.non-scalable=true label in its metadata
  • Warning appears as an inline alert in the "Edit Pod count" modal and as a tooltip on the PodRing scale-up button
  • Implements a useNonScalableImageCheck hook that resolves ImageStreamTag references from Deployment trigger annotations or DeploymentConfig ImageChange triggers, fetches the IST, and checks image.dockerImageMetadata.Config.Labels for the non-scalable label

JIRA

RFE-3935

Changes

File Change
frontend/packages/console-shared/src/hooks/useNonScalableImageCheck.ts New — Hook to check for io.openshift.non-scalable label on an ImageStreamTag
frontend/public/components/modals/configure-count-modal.tsx Inline warning alert when scaling non-scalable images above 1 replica
frontend/packages/console-shared/src/components/pod/PodRing.tsx Tooltip on scale-up button for non-scalable images
frontend/public/locales/en/public.json i18n strings for modal warning
frontend/packages/console-shared/locales/en/console-shared.json i18n strings for PodRing tooltip
frontend/packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts New — 7 unit tests for the hook
frontend/public/components/modals/__tests__/configure-count-modal.spec.tsx New — 4 unit tests for the modal warning

Screenshots / Recordings

To be added by author

Test plan

  • Warning appears in "Edit Pod count" modal when scaling non-scalable image above 1 replica
  • Tooltip appears on PodRing scale-up arrow for non-scalable images
  • No warning for regular (scalable) images
  • No warning for Deployments without ImageStream triggers
  • No warning for Job parallelism path
  • Unit tests pass: yarn test packages/console-shared/src/hooks/__tests__/useNonScalableImageCheck.spec.ts (7 tests)
  • Unit tests pass: yarn test public/components/modals/__tests__/configure-count-modal.spec.tsx (4 tests)

Made with Cursor

Summary by CodeRabbit

  • New Features

  • Added detection and user-facing warnings for images marked non-scalable; warnings appear when increasing pod count and when editing replica count above one.

  • Localization

  • Added localized warning strings explaining non-scalable image constraints.

  • Tests

  • Added unit tests covering non-scalable image detection and warning display in relevant UIs.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@swshende-cmd
Copy link
Copy Markdown
Author

@jhadvig All the changes suggested are done and also verified / tested by me as per the screen prints attached .

Please help with your valuable review to further proceed. Also the console story is : https://redhat.atlassian.net/browse/CONSOLE-5296 assigned to me.

ToolTip_To_Warn NoChangesToJobsPages_ _Functionalities No_WarningOnRegularImages Warning_asSoonAs_We_Scale_Non-Scalabelmage No warning

Awaiting your kind response.

@swshende-cmd
Copy link
Copy Markdown
Author

/retest e2e-gcp-console

@swshende-cmd
Copy link
Copy Markdown
Author

/test e2e-gcp-console

@jhadvig
Copy link
Copy Markdown
Member

jhadvig commented May 19, 2026

QA Verification Evidence

Details
Branch RFE-3935
Baseline main @ ed9a644125
Candidate RFE-3935 @ 9638cac0e9
Verified 2026-05-19
Browser Playwright 1.60.0 / Chromium
OS Darwin 25.4.0
Jira CONSOLE-5296

Verification Steps

# Route Action Status
1 /k8s/ns/openshift-console/deployments/console Navigate, wait load pass
2 /k8s/ns/openshift-console/deployments/console Hover PodRing scale-up arrow pass
3 /k8s/ns/openshift-console/deployments/console Open Edit Pod count modal pass
4 /k8s/ns/openshift-console/deployments/console Increment replica count pass
5 /k8s/ns/openshift-console/deployments/downloads Navigate, check PodRing pass
6 /dashboards Navigate, wait load pass
Animated overview (click to expand)
Baseline Candidate
Step 2: PodRing hover (no tooltip) (pass)
Baseline (main) Candidate (RFE-3935)
Step 3: Edit Pod count modal (pass)
Baseline (main) Candidate (RFE-3935)
Step 4: Modal after increment (no warning) (pass)
Baseline (main) Candidate (RFE-3935)
Step 5: Downloads deployment (pass)
Baseline (main) Candidate (RFE-3935)
Step 6: Dashboard overview (pass)
Baseline (main) Candidate (RFE-3935)

Warning

This verification was performed by an AI agent. Results may contain false positives or miss
regressions that require human judgment. Always review the screenshots manually before approving.

Automated QA verification by Claude Code

Copy link
Copy Markdown
Member

@jhadvig jhadvig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @swshende-cmd adding comments for two minor issues. otherwise looks good to go 👍


const isNonScalable =
loaded && !error
? (ist as any)?.image?.dockerImageMetadata?.Config?.Labels?.[NON_SCALABLE_LABEL] === 'true'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add appropriate type

() => (resource ? getISTReference(resource) : null),
// Depend on stable primitives to avoid recomputing on every watch cycle
// eslint-disable-next-line react-hooks/exhaustive-deps
[resourceKind, resourceNamespace, triggerAnnotation, dcTriggers],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that dcTriggers is resource?.spec?.triggers an array reference that changes on every K8s watch cycle, even if the content is identical. The other three deps (resourceKind, resourceNamespace, triggerAnnotation) are all strings, so they're stable...

The fix: extract the one piece of data you actually care about from the triggers array — the IST name — as a string:

  const dcISTName = resource?.spec?.triggers?.find(
    (t) =>
      t?.type === 'ImageChange' &&
      t?.imageChangeParams?.from?.kind === 'ImageStreamTag',
  )?.imageChangeParams?.from?.name;

  const istRef = useMemo(
    () => (resource ? getISTReference(resource) : null),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [resourceKind, resourceNamespace, triggerAnnotation, dcISTName],
  );

- Replace `(ist as any)` with a proper `ImageStreamTagResource` type
  that extends K8sResourceKind with the IST-specific `image` property
- Replace `dcTriggers` array dep (unstable reference) with `dcISTName`
  string primitive extracted from the triggers array

Co-authored-by: Cursor <cursoragent@cursor.com>
@swshende-cmd
Copy link
Copy Markdown
Author

@jhadvig I have made necessary changes, hope we are good to go ahead now

@jhadvig
Copy link
Copy Markdown
Member

jhadvig commented May 19, 2026

/lgtm
/approve
/verified by @jhadvig

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label May 19, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

@jhadvig: This PR has been marked as verified by @jhadvig.

Details

In response to this:

/lgtm
/approve
/verified by @jhadvig

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label May 19, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhadvig, swshende-cmd

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 19, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

@swshende-cmd: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/shared Related to console-shared jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated lgtm Indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants